package com.sinodata.bsm.cicp.collector.gab;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jms.JMSException;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.AbstractJDBCCollector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.common.vo.Event;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * <p>
 * Description: 漏水监控
 * dbtype:sqlserver
 * dbname:GNCDB
 * ip:10.1.0.183 administrator/gab    
 * user/pwd:gncsys/gncsys88
 * port:1433
 * </p>
 *
 * @author wangpeng
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2013-7-30 下午5:02:59          wangpeng        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class LouShuiCollector extends AbstractJDBCCollector {
    private static final Logger logger = Logger.getLogger(LouShuiCollector.class);
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    private static final String TIMESTAMP_KEY = "luoshui";

    @Override
    public String[] getPropMeta() {
        return null;
    }

    @Override
    public String[] getParamMeta() {
        return null;
    }

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        String resIdStr = this.getParamMap().get("resId");
        String dbType = this.getParamMap().get("dbType");
        String dbName = this.getParamMap().get("dbName");
        logger.error(">>> loushui:resIdStr[" + resIdStr + "];dbType[" + dbType + "];dbName[" + dbName + "]");
        Long resId = null;
        if (resIdStr == null || resIdStr.trim().matches("\\d+")) {
            resId = Long.valueOf(resIdStr.trim());
        } else {
            throw new CollectorException(">>>>   漏水监控,资源ID为空,或者不是数字   <<<<");
        }
        String timestamp = getTimes();
        logger.error(">>> loushui：timestamp[" + timestamp + "]");
        String sql = getSql(timestamp);
        List<Event> newEventList = new ArrayList<Event>();
        List<Event> confimedEventList = new ArrayList<Event>();
        try {
            Long timestampLong = sdf.parse(timestamp).getTime();//时间戳转换为毫秒数
            ResultSet rs = this.getCachedResultSet(dbType, ip, dbName, sql);
            logger.error(">>> " + Class.class.getName() + ".collect() ip[" + ip + "]sql[" + sql + "] rs[" + rs + "]");
            while (rs != null && rs.next()) {
                String objectId = rs.getString("objectId");
                Date occurTime = rs.getDate("occurTime");
                Integer level = rs.getInt("level");
                String msg = rs.getString("msg");
                Integer status = rs.getInt("status");
                Date confirmTime = rs.getDate("confirmTime");
                timestamp = sdf.format(occurTime);
                if (status == 0) {//出现漏水，并且还未修复
                    logger.error("loushui>>>status=" + status + " occur a new event");
                    Event e = new Event();
                    e.setResId(resId);
                    e.setObjectId(objectId);
                    e.setOccurTime(occurTime);
                    e.setLevel(level);
                    //e.setConfirmTime(confirmTime);
                    e.setMsg(msg);
                    e.setStatus(status);
                    e.setEventTypeId(602009010000001L);
                    e.setCatalog(1);
                    newEventList.add(e);
                } else if (occurTime.getTime() < timestampLong) { //本次采集之前漏水，现在已经修复，产生恢复事件CATALOG=2，status =2
                    logger.error("loushui>>>status=" + status + " occur a confime event");
                    Event e2 = new Event();
                    e2.setResId(resId);
                    e2.setObjectId(objectId);
                    e2.setOccurTime(occurTime);
                    e2.setLevel(level);
                    e2.setConfirmTime(confirmTime);
                    e2.setMsg(msg);
                    e2.setStatus(2);
                    e2.setEventTypeId(602009010000001L);
                    e2.setCatalog(2);
                    confimedEventList.add(e2);
                } else {//上一次采集之后才出现漏水，并且本次采集前已经修复漏水处。
                    logger.error("loushui>>>status=" + status + ",occur two events");
                    //先产生事件
                    Event e = new Event();
                    e.setResId(resId);
                    e.setObjectId(objectId);
                    e.setOccurTime(occurTime);
                    e.setLevel(level);
                    //e.setConfirmTime(confirmTime);
                    e.setMsg(msg);
                    e.setStatus(0);
                    e.setEventTypeId(602009010000001L);
                    e.setCatalog(1);
                    newEventList.add(e);
                    //然后清除事件
                    Event e2 = new Event();
                    e2.setResId(resId);
                    e2.setObjectId(objectId);
                    e2.setOccurTime(occurTime);
                    e2.setLevel(level);
                    e2.setConfirmTime(confirmTime);
                    e2.setMsg(msg);
                    e2.setStatus(2);
                    e2.setEventTypeId(602009010000001L);
                    e2.setCatalog(2);
                    confimedEventList.add(e2);
                }
            }
            saveTimestamp(TIMESTAMP_KEY, timestamp);
            sendEvents(newEventList);
            Thread.sleep(1000);
            sendEvents(confimedEventList);
        } catch (Exception e) {
            logger.error(">>> " + Class.class.getName() + ".collect() occur error:ip[" + ip + "]sql[" + sql + "]");
            throw new CollectorException(e);
        }
        return null;
    }

    private String getSql(String timestamp) {
        StringBuffer buffer = new StringBuffer();
        buffer.append("select ");
        buffer.append("convert(varchar, w.gid) + '#' + w.hostname + '#' + w.subkey + '#' + convert(varchar, w.wtime) as objectId,"); //objectId
        buffer.append("w.wtime as occurTime,"); //产生时间
        buffer.append("w.wlevel +2  as level,");//事件级别[1-3] 分别对应：警告、重大、严重
        buffer.append("w.content + ',' + v.descr + '=' + d.originval as msg,"); //告警消息
        buffer.append("w.solved as status,"); //事件状态[01]
        buffer.append("w.wetime as confirmTime ");//事件清除时间
        buffer.append("from ");
        buffer.append("dbo.gnc_autosubwarn w,");
        buffer.append("dbo.gnc_subdevice d, ");
        buffer.append("dbo.gnc_valuetype v ");
        buffer.append("where ");
        buffer.append("w.gid = d.gid ");
        buffer.append("and w.hostname = d.hostname ");
        buffer.append("and w.subkey = d.subkey ");
        buffer.append("and d.valuetype = v.typeid ");
        buffer.append("and ((w.wtime > cast('");
        buffer.append(timestamp);
        buffer.append("' as datetime)) ");
        buffer.append("or ");
        buffer.append("(w.wetime > cast('");
        buffer.append(timestamp);
        buffer.append("' as datetime)))  ");
        buffer.append("order by w.wtime asc");
        String sql = buffer.toString();
        logger.info(sql);
        return sql;
    }

    private void sendEvents(List<Event> events) throws JMSException {
        if (events != null && events.size() > 0) {
            for (Event e : events) {
                com.sinodata.bsm.cicp.message.Messenger.getInstance().sendEvent(e);
            }
        }
    }

    private void saveTimestamp(String key, String data) throws IOException {
        String fileName = "save/" + key + ".od";
        File file = new File(fileName);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileUtils.writeStringToFile(file, data);
    }

    private Serializable getTimestamp(String key) throws IOException, ClassNotFoundException {
        String fileName = "save/" + key + ".od";
        File file = new File(fileName);
        if (!file.exists()) {
            return null;
        }
        return FileUtils.readFileToString(file);
    }

    /**
     * 第一次采集时，调用此方法获取时间戳
     * @return
     */
    private String getTimes() {
        try {
            String timestamp = (String) getTimestamp(TIMESTAMP_KEY);
            return timestamp == null ? sdf.format(new Date()) : timestamp;
        } catch (Exception e) {
            logger.error("漏水监控获取save目录下的时间戳失败");
            return sdf.format(new Date());
        }
    }

    public static void main(String[] args) {

    }

}
